package com.seed.uaa.util;

import com.seed.core.action.Action;
import com.seed.core.column.Column;
import com.seed.core.enumeration.ActionType;
import com.seed.core.pojo.seed.*;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.*;

public class MergeUtil {

    public static Map<String, Seed> initSeeds(Map<String, Seed> seeds, Map<String, Seed> libSeeds, Map<String, Seed> otherSeeds) {
        if(seeds == null && libSeeds == null && otherSeeds == null) return null;

        Set<String> seedNames = new HashSet<>();
        if(seeds != null) seedNames.addAll(seeds.keySet());
        if(libSeeds != null) seedNames.addAll(libSeeds.keySet());
        if(otherSeeds != null) seedNames.addAll(otherSeeds.keySet());
        if(seedNames.isEmpty()) return null;

        Map<String, Seed> ret = new HashMap<>();
        for(String seedName: seedNames) {
            Seed seed = seeds == null ? null : seeds.get(seedName);
            Seed libSeed = libSeeds == null ? null : libSeeds.get(seedName);
            Seed otherSeed = otherSeeds == null ? null : otherSeeds.get(seedName);
            ret.put(seedName, mergeSeed(seed, libSeed, otherSeed));
        }

        for(Map.Entry<String, Seed> entry: ret.entrySet()) {
            Seed seed = entry.getValue();
            LinkedHashMap<String, Relation> relations = seed.getRelations();
            if(relations == null) continue;

            for(Map.Entry<String, Relation> e: relations.entrySet()) {
                Relation relation = e.getValue();
                Seed targetSeed = ret.get(relation.getTargetSeedName());
                relation.setSelfSeed(seed);
                relation.setTargetSeed(targetSeed);
            }
        }

        return ret;
    }

    public static Map<String, Action> initActions(Map<String, Action> actions, Map<String, Action> libActions, Map<String, Action> otherActions) {
//        if(actionList == null && libActionList == null && otherActionList == null) return null;
//
//        Map<String, Action> emptyMap = Collections.emptyMap();
//        Map<String, Action> actions = actionList == null ? emptyMap : formatActions(actionList);
//        Map<String, Action> libActions = libActionList == null ? emptyMap : formatActions(libActionList);
//        Map<String, Action> otherActions = otherActionList == null ? emptyMap : formatActions(otherActionList);
//
//        Set<String> actionNames = new HashSet<>();
//        actionNames.addAll(actions.keySet());
//        actionNames.addAll(libActions.keySet());
//        actionNames.addAll(otherActions.keySet());
//        if(actionNames.isEmpty()) return null;
//
//        Map<String, Action> ret = new HashMap<>();
//        for(String actionName: actionNames) {
//            Action action = actions.get(actionName);
//            Action libAction = libActions.get(actionName);
//            Action otherAction = otherActions.get(actionName);
//            Action mergeAction = mergeAction(action, libAction, otherAction);
//            if(mergeAction != null) ret.put(actionName, mergeAction);
//        }
//
//        return ret;
        return mergeActions1(actions, libActions, otherActions);
    }

    private static Seed mergeSeed(Seed seed, Seed libSeed, Seed otherSeed) {
        Seed ret = new Seed();

        if(libSeed != null && libSeed.getName() != null) ret.setName(libSeed.getName());
        else if(otherSeed != null && otherSeed.getName() != null) ret.setName(otherSeed.getName());
        else if(seed != null && seed.getName() != null) ret.setName(seed.getName());

        if(libSeed != null && libSeed.getType() != null) ret.setType(libSeed.getType());
        else if(otherSeed != null && otherSeed.getType() != null) ret.setType(otherSeed.getType());
        else if(seed != null && seed.getType() != null) ret.setType(seed.getType());

        if(libSeed != null && libSeed.getTableName() != null) ret.setTableName(libSeed.getTableName());
        else if(otherSeed != null && otherSeed.getTableName() != null) ret.setTableName(otherSeed.getTableName());
        else if(seed != null && seed.getTableName() != null) ret.setTableName(seed.getTableName());

        if(libSeed != null && libSeed.getTableSchema() != null) ret.setTableSchema(libSeed.getTableSchema());
        else if(otherSeed != null && otherSeed.getTableSchema() != null) ret.setTableSchema(otherSeed.getTableSchema());
        else if(seed != null && seed.getTableSchema() != null) ret.setTableSchema(seed.getTableSchema());

        if(seed != null && seed.getLabel() != null) ret.setLabel(seed.getLabel());
        else if(otherSeed != null && otherSeed.getLabel() != null) ret.setLabel(otherSeed.getLabel());
        else if(libSeed != null && libSeed.getLabel() != null) ret.setLabel(libSeed.getLabel());

        if(seed != null && seed.getComment() != null) ret.setComment(seed.getComment());
        else if(otherSeed != null && otherSeed.getComment() != null) ret.setComment(otherSeed.getComment());
        else if(libSeed != null && libSeed.getComment() != null) ret.setComment(libSeed.getComment());

        if(libSeed != null && libSeed.getNameColumn() != null) ret.setNameColumn(libSeed.getNameColumn());
        else if(otherSeed != null && otherSeed.getNameColumn() != null) ret.setNameColumn(otherSeed.getNameColumn());
        else if(seed != null && seed.getNameColumn() != null) ret.setNameColumn(seed.getNameColumn());

        List<String> declares = seed != null && seed.getDeclares() != null ? seed.getDeclares() : null;
        List<String> libDeclares = libSeed != null && libSeed.getDeclares() != null ? libSeed.getDeclares() : null;
        List<String> otherDeclares = otherSeed != null && otherSeed.getDeclares() != null ? otherSeed.getDeclares() : null;
        List<String> mergeDeclares = merge(declares, libDeclares, otherDeclares);
        if(mergeDeclares != null) ret.setDeclares(mergeDeclares);

        List<String> searches = seed != null && seed.getSearches() != null ? seed.getSearches() : null;
        List<String> libSearches = libSeed != null && libSeed.getSearches() != null ? libSeed.getSearches() : null;
        List<String> otherSearches = otherSeed != null && otherSeed.getSearches() != null ? otherSeed.getSearches() : null;
        List<String> mergeSearches = merge(searches, libSearches, otherSearches);
        if(mergeSearches != null) ret.setSearches(mergeSearches);

        List<String> orders = seed != null && seed.getOrders() != null ? seed.getOrders() : null;
        List<String> libOrders = libSeed != null && libSeed.getOrders() != null ? libSeed.getOrders() : null;
        List<String> otherOrders = otherSeed != null && otherSeed.getOrders() != null ? otherSeed.getOrders() : null;
        List<String> mergeOrders = merge(orders, libOrders, otherOrders);
        if(mergeOrders != null) ret.setOrders(mergeOrders);

        if(libSeed != null && libSeed.getCheckLogin() != null) ret.setCheckLogin(libSeed.getCheckLogin());
        else if(otherSeed != null && otherSeed.getCheckLogin() != null) ret.setCheckLogin(otherSeed.getCheckLogin());
        else if(seed != null && seed.getCheckLogin() != null) ret.setCheckLogin(seed.getCheckLogin());

        if(libSeed != null && libSeed.getCheckAction() != null) ret.setCheckAction(libSeed.getCheckAction());
        else if(otherSeed != null && otherSeed.getCheckAction() != null) ret.setCheckAction(otherSeed.getCheckAction());
        else if(seed != null && seed.getCheckAction() != null) ret.setCheckAction(seed.getCheckAction());

//        if(libSeed != null && libSeed.getCheckData() != null) ret.setCheckData(libSeed.getCheckData());
//        else if(otherSeed != null && otherSeed.getCheckData() != null) ret.setCheckData(otherSeed.getCheckData());
//        else if(seed != null && seed.getCheckData() != null) ret.setCheckData(seed.getCheckData());
//
//        if(libSeed != null && libSeed.getCheckField() != null) ret.setCheckField(libSeed.getCheckField());
//        else if(otherSeed != null && otherSeed.getCheckField() != null) ret.setCheckField(otherSeed.getCheckField());
//        else if(seed != null && seed.getCheckField() != null) ret.setCheckField(seed.getCheckField());
//
//        if(libSeed != null && libSeed.getUseKeyword() != null) ret.setUseKeyword(libSeed.getUseKeyword());
//        else if(otherSeed != null && otherSeed.getUseKeyword() != null) ret.setUseKeyword(otherSeed.getUseKeyword());
//        else if(seed != null && seed.getUseKeyword() != null) ret.setUseKeyword(seed.getUseKeyword());

        if(libSeed != null && libSeed.getOnSave() != null) ret.setOnSave(libSeed.getOnSave());
        else if(otherSeed != null && otherSeed.getOnSave() != null) ret.setOnSave(otherSeed.getOnSave());
        else if(seed != null && seed.getOnSave() != null) ret.setOnSave(seed.getOnSave());

        if(libSeed != null && libSeed.getOnUpdate() != null) ret.setOnUpdate(libSeed.getOnUpdate());
        else if(otherSeed != null && otherSeed.getOnUpdate() != null) ret.setOnUpdate(otherSeed.getOnUpdate());
        else if(seed != null && seed.getOnUpdate() != null) ret.setOnUpdate(seed.getOnUpdate());

        if(libSeed != null && libSeed.getOnSet() != null) ret.setOnSet(libSeed.getOnSet());
        else if(otherSeed != null && otherSeed.getOnSet() != null) ret.setOnSet(otherSeed.getOnSet());
        else if(seed != null && seed.getOnSet() != null) ret.setOnSet(seed.getOnSet());

        Map<String, Action> actions = seed != null && seed.getActions() != null ? seed.getActions() : null;
        Map<String, Action> libActions = libSeed != null && libSeed.getActions() != null ? libSeed.getActions() : null;
        Map<String, Action> otherActions = otherSeed != null && otherSeed.getActions() != null ? otherSeed.getActions() : null;
        Map<String, Action> mergeActions = mergeActions1(actions, libActions, otherActions);
        if(mergeActions != null) ret.setActions(mergeActions);

        Map<String, Column> columns = seed != null && seed.getColumns() != null ? seed.getColumns() : null;
        Map<String, Column> libColumns = libSeed != null && libSeed.getColumns() != null ? libSeed.getColumns() : null;
        Map<String, Column> otherColumns = otherSeed != null && otherSeed.getColumns() != null ? otherSeed.getColumns() : null;
        LinkedHashMap<String, Column> mergeColumns = mergeColumns(columns, libColumns, otherColumns);
        if(mergeColumns != null) ret.setColumns(mergeColumns);

        Map<String, Relation> relations = seed != null && seed.getRelations() != null ? seed.getRelations() : null;
        Map<String, Relation> libRelations = libSeed != null && libSeed.getRelations() != null ? libSeed.getRelations() : null;
        Map<String, Relation> otherRelations = otherSeed != null && otherSeed.getRelations() != null ? otherSeed.getRelations() : null;
        LinkedHashMap<String, Relation> mergeRelations = mergeRelations(relations, libRelations, otherRelations);
        if(mergeRelations != null) ret.setRelations(mergeRelations);

        Map<String, Stat> stats = seed != null && seed.getStats() != null ? seed.getStats() : null;
        Map<String, Stat> libStats = libSeed != null && libSeed.getStats() != null ? libSeed.getStats() : null;
        Map<String, Stat> otherStats = otherSeed != null && otherSeed.getStats() != null ? otherSeed.getStats() : null;
        Map<String, Stat> mergeStats = mergeStats(stats, libStats, otherStats);
        if(mergeStats != null) ret.setStats(mergeStats);

        return ret;
    }

    private static Map<String, Action> mergeActions1(Map<String, Action> actions, Map<String, Action> libActions, Map<String, Action> otherActions) {
        if(actions == null && libActions == null && otherActions == null) return null;

        Set<String> actionNames = new HashSet<>();
        if(actions != null) actionNames.addAll(actions.keySet());
        if(libActions != null) actionNames.addAll(libActions.keySet());
        if(otherActions != null) actionNames.addAll(otherActions.keySet());
        if(actionNames.isEmpty()) return null;

        LinkedHashMap<String, Action> ret = new LinkedHashMap<>();
        for(String actionName: actionNames) {
            Action action = actions == null ? null : actions.get(actionName);
            Action libAction = libActions == null ? null : libActions.get(actionName);
            Action otherAction = otherActions == null ? null : otherActions.get(actionName);
            Action mergeAction = mergeAction(action, libAction, otherAction);
            if(mergeAction != null) ret.put(actionName, mergeAction);
        }
        return ret;
    }

    private static Action mergeAction(Action action, Action libAction, Action otherAction) {
        if(action == null && libAction == null && otherAction == null) return null;

        Action ret = null; // new Action();

//        if(libAction != null && libAction.getName() != null) ret.setName(libAction.getName());
//        else if(otherAction != null && otherAction.getName() != null) ret.setName(otherAction.getName());
//        else if(action != null && action.getName() != null) ret.setName(action.getName());
//
//        if(libAction != null && libAction.getType() != null) ret.setType(libAction.getType());
//        else if(otherAction != null && otherAction.getType() != null) ret.setType(otherAction.getType());
//        else if(action != null && action.getType() != null) ret.setType(action.getType());
//
//        if(libAction != null && libAction.getMethods() != null) ret.setMethods(libAction.getMethods());
//        else if(otherAction != null && otherAction.getMethods() != null) ret.setMethods(otherAction.getMethods());
//        else if(action != null && action.getMethods() != null) ret.setMethods(action.getMethods());
//
//        if(libAction != null && libAction.getDeclare() != null) ret.setDeclare(libAction.getDeclare());
//        else if(otherAction != null && otherAction.getDeclare() != null) ret.setDeclare(otherAction.getDeclare());
//        else if(action != null && action.getDeclare() != null) ret.setDeclare(action.getDeclare());
//
//        if(libAction != null && libAction.getDeclareValue() != null) ret.setDeclareValue(libAction.getDeclareValue());
//        else if(otherAction != null && otherAction.getDeclareValue() != null) ret.setDeclareValue(otherAction.getDeclareValue());
//        else if(action != null && action.getDeclareValue() != null) ret.setDeclareValue(action.getDeclareValue());
//
//        if(libAction != null && libAction.getSeedName() != null) ret.setSeedName(libAction.getSeedName());
//        else if(otherAction != null && otherAction.getSeedName() != null) ret.setSeedName(otherAction.getSeedName());
//        else if(action != null && action.getSeedName() != null) ret.setSeedName(action.getSeedName());
//
//        List<String> declares = action != null && action.getDeclares() != null ? action.getDeclares() : null;
//        List<String> libDeclares = libAction != null && libAction.getDeclares() != null ? libAction.getDeclares() : null;
//        List<String> otherDeclares = otherAction != null && otherAction.getDeclares() != null ? otherAction.getDeclares() : null;
//        List<String> mergeDeclares = merge(declares, libDeclares, otherDeclares);
//        if(mergeDeclares != null) ret.setDeclares(mergeDeclares);
//
//        List<String> searches = action != null && action.getSearches() != null ? action.getSearches() : null;
//        List<String> libSearches = libAction != null && libAction.getSearches() != null ? libAction.getSearches() : null;
//        List<String> otherSearches = otherAction != null && otherAction.getSearches() != null ? otherAction.getSearches() : null;
//        List<String> mergeSearches = merge(searches, libSearches, otherSearches);
//        if(mergeSearches != null) ret.setSearches(mergeSearches);
//
//        List<String> orders = action != null && action.getOrders() != null ? action.getOrders() : null;
//        List<String> libOrders = libAction != null && libAction.getOrders() != null ? libAction.getOrders() : null;
//        List<String> otherOrders = otherAction != null && otherAction.getOrders() != null ? otherAction.getOrders() : null;
//        List<String> mergeOrders = merge(orders, libOrders, otherOrders);
//        if(mergeOrders != null) ret.setOrders(mergeOrders);
//
//        Map<String, Stat> stats = action != null && action.getStats() != null ? action.getStats() : null;
//        Map<String, Stat> libStats = libAction != null && libAction.getStats() != null ? libAction.getStats() : null;
//        Map<String, Stat> otherStats = otherAction != null && otherAction.getStats() != null ? otherAction.getStats() : null;
//        Map<String, Stat> mergeStats = mergeStats(stats, libStats, otherStats);
//        if(mergeStats != null) ret.setStats(mergeStats);

        if(libAction != null && libAction.getCheckLogin() != null) ret.setCheckLogin(libAction.getCheckLogin());
        else if(otherAction != null && otherAction.getCheckLogin() != null) ret.setCheckLogin(otherAction.getCheckLogin());
        else if(action != null && action.getCheckLogin() != null) ret.setCheckLogin(action.getCheckLogin());

        if(libAction != null && libAction.getCheckAction() != null) ret.setCheckAction(libAction.getCheckAction());
        else if(otherAction != null && otherAction.getCheckAction() != null) ret.setCheckAction(otherAction.getCheckAction());
        else if(action != null && action.getCheckAction() != null) ret.setCheckAction(action.getCheckAction());

        return ret;
    }

    private static List<String> merge(List<String> list, List<String> libList, List<String> otherList) {
        if(list == null && libList == null && otherList == null) return null;

        List<String> ret = new ArrayList<>();
        if(libList != null) ret.addAll(libList);
        if(otherList != null) ret.addAll(otherList);
        if(list != null) ret.addAll(list);

        return ret.stream().distinct().toList();
    }

    private static LinkedHashMap<String, Column> mergeActionColumns(Map<String, Column> columns, Map<String, Column> libColumns, Map<String, Column> otherColumns) {
        if(columns == null && libColumns == null && otherColumns == null) return null;

        Set<String> columnNames = new HashSet<>();
        if(columns != null) columnNames.addAll(columns.keySet());
        if(libColumns != null) columnNames.addAll(libColumns.keySet());
        if(otherColumns != null) columnNames.addAll(otherColumns.keySet());
        if(columnNames.isEmpty()) return null;

        LinkedHashMap<String, Column> ret = new LinkedHashMap<>();
        for(String columnName: columnNames) {
            Column column = columns == null ? null : columns.get(columnName);
            Column libColumn = libColumns == null ? null : libColumns.get(columnName);
            Column otherColumn = otherColumns == null ? null : otherColumns.get(columnName);
            if(column != null) ret.put(columnName, column);
            else if(otherColumn != null) ret.put(columnName, otherColumn);
            else if(libColumn != null) ret.put(columnName, libColumn);
        }

        return ret;
    }

    private static LinkedHashMap<String, Column> mergeColumns(Map<String, Column> columns, Map<String, Column> libColumns, Map<String, Column> otherColumns) {
        if(columns == null && libColumns == null && otherColumns == null) return null;

        Set<String> columnNames = new HashSet<>();
        if(columns != null) columnNames.addAll(columns.keySet());
        if(libColumns != null) columnNames.addAll(libColumns.keySet());
        if(otherColumns != null) columnNames.addAll(otherColumns.keySet());
        if(columnNames.isEmpty()) return null;

        LinkedHashMap<String, Column> ret = new LinkedHashMap<>();
        for(String columnName: columnNames) {
            Column column = columns == null ? null : columns.get(columnName);
            Column libColumn = libColumns == null ? null : libColumns.get(columnName);
            Column otherColumn = otherColumns == null ? null : otherColumns.get(columnName);
            if(libColumn != null) ret.put(columnName, libColumn);
            else if(otherColumn != null) ret.put(columnName, otherColumn);
            else if(column != null) ret.put(columnName, column);
        }

        return ret;
    }

    private static LinkedHashMap<String, Relation> mergeRelations(Map<String, Relation> relations, Map<String, Relation> libRelations, Map<String, Relation> otherRelations) {
        if(relations == null && libRelations == null && otherRelations == null) return null;

        Set<String> crosses = new HashSet<>();
        if(relations != null) crosses.addAll(relations.keySet());
        if(libRelations != null) crosses.addAll(libRelations.keySet());
        if(otherRelations != null) crosses.addAll(otherRelations.keySet());
        if(crosses.isEmpty()) return null;

        LinkedHashMap<String, Relation> ret = new LinkedHashMap<>();
        for(String cross: crosses) {
            Relation relation = relations == null ? null : relations.get(cross);
            Relation libRelation = libRelations == null ? null : libRelations.get(cross);
            Relation otherRelation = otherRelations == null ? null : otherRelations.get(cross);
            if(libRelation != null) ret.put(cross, libRelation);
            else if(otherRelation != null) ret.put(cross, otherRelation);
            else if(relation != null) ret.put(cross, relation);
        }

        return ret;
    }

    private static Map<String, Stat> mergeStats(Map<String, Stat> stats, Map<String, Stat> libStats, Map<String, Stat> otherStats) {
        if(stats == null && libStats == null && otherStats == null) return null;

        Set<String> statNames = new HashSet<>();
        if(stats != null) statNames.addAll(stats.keySet());
        if(libStats != null) statNames.addAll(libStats.keySet());
        if(otherStats != null) statNames.addAll(otherStats.keySet());
        if(statNames.isEmpty()) return null;

        Map<String, Stat> ret = new HashMap<>();
        for(String statName: statNames) {
            Stat stat = stats == null ? null : stats.get(statName);
            Stat libStat = libStats == null ? null : libStats.get(statName);
            Stat otherStat = otherStats == null ? null : otherStats.get(statName);
            if(libStat != null) ret.put(statName, libStat);
            else if(otherStat != null) ret.put(statName, otherStat);
            else if(stat != null) ret.put(statName, stat);
        }
        return ret;
    }

    // 合并配置、库以及自定义的seed和action============start==

    /**
     * 合并规则：
     * 1. 其它可以扩展库里的action, 不能覆盖库里的action
     * 2. 配置可以扩展库里和其它的action, 不能覆盖库里和其它的action
     * @param seeds 配置出来的，简称配置
     * @param libSeeds 库转化而来，简称库
     * @param otherSeeds 自定义Controller转化而来，简称其它
     * @return 合并后的数据
     */
//    public static Map<String, Seed> mergeSeeds(Map<String, Seed> seeds, Map<String, Seed> libSeeds, Map<String, Seed> otherSeeds) {
//        Map<String, Seed> ret = new HashMap<>();
//        if(libSeeds != null) {
//            for(Map.Entry<String, Seed> entry: libSeeds.entrySet()) {
//                ret.put(entry.getKey(), entry.getValue().clone());
//            }
//        }
//
//        if(otherSeeds != null) {
//            for(Map.Entry<String, Seed> entry: otherSeeds.entrySet()) {
//                String seedName = entry.getKey();
//                Seed seed = entry.getValue();
//                Seed oldSeed = ret.get(seedName);
//                if(oldSeed == null) {
//                    ret.put(seedName, seed.clone());
//                } else {
//                    mergeSeed(oldSeed, seed);
//                }
//            }
//        }
//
//        if(seeds != null) {
//            for(Map.Entry<String, Seed> entry: seeds.entrySet()) {
//                String seedName = entry.getKey();
//                Seed seed = entry.getValue();
//                Seed oldSeed = ret.get(seedName);
//                if(oldSeed == null) {
//                    ret.put(seedName, seed.clone());
//                } else {
//                    mergeSeed(oldSeed, seed);
//                }
//            }
//        }
//
//        return ret;
//    }
//
//    public static Map<String, Action> mergeActions(Map<String, Action> configActions, Map<String, Action> libActions, Map<String, Action> otherActions) {
//        Map<String, Action> ret = new HashMap<>();
//        if(libActions != null) {
//            for(Map.Entry<String, Action> entry: libActions.entrySet()) {
//                ret.put(entry.getKey(), entry.getValue().clone());
//            }
//        }
//
//        if(otherActions != null) {
//            for(Map.Entry<String, Action> entry: otherActions.entrySet()) {
//                String actionName = entry.getKey();
//                Action action = entry.getValue();
//                Action oldAction = ret.get(actionName);
//                if(oldAction == null) {
//                    ret.put(actionName, action.clone());
//                } else {
//                    mergeAction(oldAction, action);
//                }
//            }
//        }
//
//        if(configActions != null) {
//            for(Map.Entry<String, Action> entry: configActions.entrySet()) {
//                String actionName = entry.getKey();
//                Action action = entry.getValue();
//                Action oldAction = ret.get(actionName);
//                if(oldAction == null) {
//                    ret.put(actionName, action.clone());
//                } else {
//                    mergeAction(oldAction, action);
//                }
//            }
//        }
//        return ret;
//    }

    // 合并配置、库以及自定义的seed和action============end==

//    public static void mergeSeed(Seed self, Seed other) {
//        String tableName = other.getTableName();
//        if(StrUtil.isNotBlank(tableName)) self.setTableName(tableName);
//
//        String tableSchema = other.getTableSchema();
//        if(StrUtil.isNotBlank(tableSchema)) self.setTableSchema(tableSchema);
//
//        String label = other.getLabel();
//        if(StrUtil.isNotBlank(label)) self.setLabel(label);
//
//        String comment = other.getComment();
//        if(StrUtil.isNotBlank(comment)) self.setComment(comment);
//
//        String nameColumn = other.getNameColumn();
//        if(StrUtil.isNotBlank(nameColumn)) self.setNameColumn(nameColumn);
//
//        Map<String, Action> actions = other.getActions();
//        if(actions != null) mergeActions(self.getActions(), actions);
//
//        Map<String, Column> columns = other.getColumns();
//        if(columns != null) mergeColumns(self.getColumns(), columns);
//
//        Map<String, Relation> relations = other.getRelations();
//        if(relations != null) mergeRelations(self.getRelations(), relations);
//
////        if(onSave != null) ret.setOnSave(new ArrayList<>(onSave));
////        if(onUpdate != null) ret.setOnUpdate(new ArrayList<>(onUpdate));
////        if(onSet != null) ret.setOnSet(new ArrayList<>(onSet));
////
////        List<? extends OnSaveListener> onSave = seed.getOnSave();
////        if(onSave != null) {
////            for(OnSaveListener listener: onSave) ret.getOnSave().add(listener);
////            ret.setOnSave(ret.getOnSave().stream().distinct().toList());
////        }
//
//        mergeDeclares(self.getDeclares(), other.getDeclares());
//        mergeSearches(self.getSearches(), other.getSearches());
//        mergeOrders(self.getOrders(), other.getOrders());
//        mergeStats(self.getStats(), other.getStats());
//
//        Boolean checkLogin = other.getCheckLogin();
//        if(checkLogin != null) self.setCheckLogin(checkLogin);
//
//        Boolean checkAction = other.getCheckAction();
//        if(checkAction != null) self.setCheckAction(checkAction);
//
//        Boolean checkData = other.getCheckData();
//        if(checkData != null) self.setCheckData(checkData);
//
//        Boolean checkField = other.getCheckField();
//        if(checkField != null) self.setCheckField(checkField);
//
//        Boolean useKeyword = other.getUseKeyword();
//        if(useKeyword != null) self.setUseKeyword(useKeyword);
//    }

//    public static void mergeActions(Map<String, Action> self, Map<String, Action> other) {
//        Map<String, Action> adding = new HashMap<>();
//        for(Map.Entry<String, Action> entry: other.entrySet()) {
//            String actionName = entry.getKey();
//            Action otherAction = entry.getValue();
//            Action selfAction = self.get(actionName);
//            if(selfAction == null) {
//                adding.put(actionName, otherAction);
//            } else {
//                mergeAction(selfAction, otherAction);
//            }
//        }
//        self.putAll(adding);
//    }

//    public static void mergeAction(Action self, Action other) {
////        String label = other.getLabel();
////        if(StrUtil.isNotBlank(label)) self.setLabel(label);
////
////        String comment = other.getComment();
////        if(StrUtil.isNotBlank(label)) self.setComment(comment);
//
//        mergeDeclares(self.getDeclares(), other.getDeclares());
//        mergeSearches(self.getSearches(), other.getSearches());
//        mergeOrders(self.getOrders(), other.getOrders());
//        mergeStats(self.getStats(), other.getStats());
//
//        Boolean checkLogin = other.getCheckLogin();
//        if(checkLogin != null) self.setCheckLogin(checkLogin);
//
//        Boolean checkAction = other.getCheckAction();
//        if(checkAction != null) self.setCheckAction(checkAction);
//
//        Boolean checkData = other.getCheckData();
//        if(checkData != null) self.setCheckData(checkData);
//
//        Boolean checkField = other.getCheckField();
//        if(checkField != null) self.setCheckField(checkField);
//
//        Boolean useKeyword = other.getUseKeyword();
//        if(useKeyword != null) self.setUseKeyword(useKeyword);
//    }
//
//    public static void mergeColumns(Map<String, Column> self, Map<String, Column> other) {
//        Map<String, Column> adding = new HashMap<>();
//        for(Map.Entry<String, Column> entry: other.entrySet()) {
//            String columnName = entry.getKey();
//            Column otherColumn = entry.getValue();
//            Column selfColumn = self.get(columnName);
//            if(selfColumn == null) {
//                adding.put(columnName, otherColumn);
//            } else {
//                mergeColumn(selfColumn, otherColumn);
//            }
//        }
//        self.putAll(adding);
//    }

//    public static void mergeColumn(Column self, Column other) {
//        String label = other.getLabel();
//        if(StrUtil.isNotBlank(label)) self.setLabel(label);
//
//        String comment = other.getComment();
//        if(StrUtil.isNotBlank(comment)) self.setComment(comment);
//    }
//
//    public static void mergeRelations(Map<String, Relation> self, Map<String, Relation> other) {
//        Map<String, Relation> adding = new HashMap<>();
//        for(Map.Entry<String, Relation> entry: other.entrySet()) {
//            String cross = entry.getKey();
//            Relation otherRelation = entry.getValue();
//            Relation selfRelation = self.get(cross);
//            if(selfRelation == null) {
//                adding.put(cross, otherRelation);
//            } else {
//                mergeRelation(selfRelation, otherRelation);
//            }
//        }
//
//        self.putAll(adding);
//    }

//    public static void mergeRelation(Relation self, Relation other) {
//        String label = other.getLabel();
//        if(StrUtil.isNotBlank(label)) self.setLabel(label);
//
//        String comment = other.getComment();
//        if(StrUtil.isNotBlank(comment)) self.setComment(comment);
//    }
//
//    public static void mergeDeclares(List<String> self, List<String> other) {
//        if(other == null) return;
//        for(String item: other) {
//            if(!self.contains(item)) self.add(item);
//        }
//    }
//
//    public static void mergeSearches(List<String> self, List<String> other) {
//        if(other == null) return;
//        for(String item: other) {
//            if(!self.contains(item)) self.add(item);
//        }
//    }
//
//    public static void mergeOrders(List<String> self, List<String> other) {
//        if(other == null) return;
//        for(String item: other) {
//            if(!self.contains(item)) self.add(item);
//        }
//    }
//
//    public static void mergeStats(Map<String, Stat> self, Map<String, Stat> other) {
//        if(other == null) return;
//        self.putAll(other);
//    }
}
